package biz.datalk.industrialland.common.log.config;

import biz.datalk.industrialland.common.component.filter.MDCFilterTaskDecorator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author tarofang@163.com
 * @date 2020-06-24
 */
@Configuration
@EnableConfigurationProperties({LogTaskProperties.class})
@ConditionalOnProperty(name = "log-task-executor.enable", havingValue = "true", matchIfMissing = true)
public class LogThreadPoolExecutorConfig {
    private final LogTaskProperties logTaskProperties;

    @Autowired
    public LogThreadPoolExecutorConfig(LogTaskProperties logTaskProperties) {
        this.logTaskProperties = logTaskProperties;
    }

    /** 同步外部联系人线程池 */
    @Bean("logTaskThreadPoolExecutor")
    @ConditionalOnProperty(name = "log-task-executor.enable", havingValue = "true", matchIfMissing = true)
    public ThreadPoolTaskExecutor logTaskThreadPoolExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(logTaskProperties.getCorePoolSize());
        threadPoolTaskExecutor.setMaxPoolSize(logTaskProperties.getMaxPoolSize());
        threadPoolTaskExecutor.setKeepAliveSeconds(logTaskProperties.getKeepAliveSeconds());
        threadPoolTaskExecutor.setQueueCapacity(logTaskProperties.getQueueCapacity());
        threadPoolTaskExecutor.setThreadNamePrefix(logTaskProperties.getThreadNamePrefix());

        threadPoolTaskExecutor.setAllowCoreThreadTimeOut(false);
        threadPoolTaskExecutor.setDaemon(false);
        // 线程优先级
        threadPoolTaskExecutor.setThreadPriority(Thread.NORM_PRIORITY);

        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(logTaskProperties.isWaitForTasksToCompleteOnShutdown());
        threadPoolTaskExecutor.setAwaitTerminationSeconds(logTaskProperties.getAwaitTerminationSeconds());

        // setRejectedExecutionHandler：当pool已经达到max size的时候，如何处理新任务
        // CallerRunsPolicy：不在新线程中执行任务，而是由调用者所在的线程来执行
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        threadPoolTaskExecutor.setTaskDecorator(new MDCFilterTaskDecorator());

        threadPoolTaskExecutor.afterPropertiesSet();
        return threadPoolTaskExecutor;
    }

    /** 同步外部联系人 Semaphore */
    @Bean("logTaskSemaphore")
    @ConditionalOnProperty(name = "log-task-executor.enable", havingValue = "true")
    public Semaphore logTaskSemaphore() {
        return new Semaphore(logTaskProperties.getSemaphoreNum());
    }
}
